//
// Created by mgr on 2019/1/3.
//
#include "CRuisBaseWindow.h"
#include "base/RuisUIException.h"

namespace cliMain {
    CRuisBaseWindow::CRuisBaseWindow(LPCTSTR name,LPCTSTR skinfile) {
        mName = name;
        skinFile = skinfile;
    }


    CRuisBaseWindow::~CRuisBaseWindow() {
    }


    CDuiString CRuisBaseWindow::GetSkinFolder() {
        return CDuiString(_T("skin\\ruis\\"));
    }

    CDuiString CRuisBaseWindow::GetSkinFile() {
        return skinFile;
    }

    LPCTSTR CRuisBaseWindow::GetWindowClassName() const
    {
        return mName.GetData();
    }

    UINT CRuisBaseWindow::GetClassStyle() const
    {
        return UI_CLASSSTYLE_FRAME | CS_DBLCLKS;
    }

    void CRuisBaseWindow::InitWindow() // 本例中此函数其实没有做任何事情
    {
        m_pBtnOK = static_cast<CButtonUI *>(m_PaintManager.FindControl(TEXT("OK")));
        if (m_pBtnOK == NULL)
            return;
        // m_pBtnOK->OnNotify += MakeDelegate(this, &CRuisBaseWindow::OnOK);
        // MakeDelegate的实现感觉很强大，这样也可以实现把OK按钮的时间转接到OnOK来处理

        m_pBtnCancel = static_cast<CButtonUI *>(m_PaintManager.FindControl(TEXT("Close")));
        if (m_pBtnCancel == NULL)
            return;
        //m_pBtnCancel->OnNotify += MakeDelegate(this, &CRuisBaseWindow::OnClose);
    }

    void CRuisBaseWindow::OnFinalMessage(HWND /*hWnd*/)
    {
        //delete this;
    }

    LRESULT CRuisBaseWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        LRESULT lRes = 0;
        BOOL bHandled = TRUE;
        switch (uMsg)
        {
            case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
            case WM_CLOSE:         lRes = OnClose(uMsg, wParam, lParam, bHandled); break;
            case WM_DESTROY:       lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break;
            case WM_NCACTIVATE:    lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
            case WM_NCCALCSIZE:    lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
            case WM_NCPAINT:       lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;
            case WM_PAINT:		   lRes = OnPaint(uMsg, wParam, lParam, bHandled); break;
            case WM_NCHITTEST:     lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
            case WM_SIZE:          lRes = OnSize(uMsg, wParam, lParam, bHandled); break;
            case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break;
            case WM_SYSCOMMAND:    lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break;
            default:
                bHandled = FALSE; break;
        }

        if (bHandled) return lRes;
        if (m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes) != 0)
            return lRes;
        return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
    }

    void CRuisBaseWindow::Notify(TNotifyUI& msg)
    {
        if (msg.sType == DUI_MSGTYPE_WINDOWINIT) // 先判断消息类型
        {
            InitWindow();
        }
    }

    LRESULT CRuisBaseWindow::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
        styleValue &= ~WS_CAPTION;
        ::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);

        m_PaintManager.Init(m_hWnd); // 把自己的窗口句柄与窗口绘制管理器挂接在一起  
        CDialogBuilder builder;
        CControlUI* pRoot = builder.Create(GetSkinFile().GetData(), (UINT)0, NULL, &m_PaintManager);
        if (pRoot == NULL){
            throw RuisUIException(_T("找不到皮肤文件，打开失败"));
        }else{
            m_PaintManager.AttachDialog(pRoot); // 把上面的控件绘制到本窗口上，之前有把m_hWnd传给m_PaintManager  
            m_PaintManager.AddNotifier(this); // 把自己加入到CPaintManagerUI的m_aNotifiers数组中，用于处理Notify函数  
            Init();
            return 0;
        }

    }

    LRESULT CRuisBaseWindow::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        bHandled = FALSE;
        return 0;
    }

    LRESULT CRuisBaseWindow::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
//        ::PostQuitMessage(0L);

        bHandled = FALSE;
        return 0;
    }

    LRESULT CRuisBaseWindow::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        if (::IsIconic(*this)) bHandled = FALSE;
        return (wParam == 0) ? TRUE : FALSE;
    }

    LRESULT CRuisBaseWindow::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        return 0;
    }

    LRESULT CRuisBaseWindow::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        return 0;
    }

    LRESULT CRuisBaseWindow::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        bHandled = FALSE;
        return 0;
    }

    LRESULT CRuisBaseWindow::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
        ::ScreenToClient(*this, &pt);

        RECT rcClient;
        ::GetClientRect(*this, &rcClient);

        if( !::IsZoomed(*this) ) {
            RECT rcSizeBox = m_PaintManager.GetSizeBox();
            if( pt.y < rcClient.top + rcSizeBox.top ) {
                if( pt.x < rcClient.left + rcSizeBox.left ) return HTTOPLEFT;
                if( pt.x > rcClient.right - rcSizeBox.right ) return HTTOPRIGHT;
                return HTTOP;
            }
            else if( pt.y > rcClient.bottom - rcSizeBox.bottom ) {
                if( pt.x < rcClient.left + rcSizeBox.left ) return HTBOTTOMLEFT;
                if( pt.x > rcClient.right - rcSizeBox.right ) return HTBOTTOMRIGHT;
                return HTBOTTOM;
            }
            if( pt.x < rcClient.left + rcSizeBox.left ) return HTLEFT;
            if( pt.x > rcClient.right - rcSizeBox.right ) return HTRIGHT;
        }

        RECT rcCaption = m_PaintManager.GetCaptionRect();
        if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
		&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom) {
            CControlUI* pControl = m_PaintManager.FindControl(pt);
            if (pControl && _tcscmp(pControl->GetClass(), _T("ButtonUI")) != 0 &&
                _tcscmp(pControl->GetClass(), _T("OptionUI")) != 0 &&
                _tcscmp(pControl->GetClass(), _T("TextUI")) != 0)//判断不是按钮的控件才可以拖动
                return HTCAPTION;
        }

        return HTCLIENT;
    }

    LRESULT CRuisBaseWindow::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        SIZE szRoundCorner = m_PaintManager.GetRoundCorner();
        if (!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) {
            CDuiRect rcWnd;
            ::GetWindowRect(*this, &rcWnd);
            rcWnd.Offset(-rcWnd.left, -rcWnd.top);
            rcWnd.right++; rcWnd.bottom++;
            HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
            ::SetWindowRgn(*this, hRgn, TRUE);
            ::DeleteObject(hRgn);
        }

        bHandled = FALSE;
        return 0;
    }

    LRESULT CRuisBaseWindow::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        MONITORINFO oMonitor = {};
        oMonitor.cbSize = sizeof(oMonitor);
        ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
        CDuiRect rcWork = oMonitor.rcWork;
        rcWork.Offset(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top);

        LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
        lpMMI->ptMaxPosition.x = rcWork.left;
        lpMMI->ptMaxPosition.y = rcWork.top;
        lpMMI->ptMaxSize.x = rcWork.right;
        lpMMI->ptMaxSize.y = rcWork.bottom;

        bHandled = FALSE;
        return 0;
    }

    LRESULT CRuisBaseWindow::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        // 有时会在收到WM_NCDESTROY后收到wParam为SC_CLOSE的WM_SYSCOMMAND
        if (wParam == SC_CLOSE) {
            ::PostQuitMessage(0L);
            bHandled = TRUE;
            return 0;
        }
        BOOL bZoomed = ::IsZoomed(*this);
        LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
        if (::IsZoomed(*this) != bZoomed) {
            /*if (!bZoomed) {
                CControlUI* pControl = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("maxbtn")));
                if (pControl) pControl->SetVisible(false);
                pControl = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("restorebtn")));
                if (pControl) pControl->SetVisible(true);
            }
            else {
                CControlUI* pControl = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("maxbtn")));
                if (pControl) pControl->SetVisible(true);
                pControl = static_cast<CControlUI*>(m_PaintManager.FindControl(_T("restorebtn")));
                if (pControl) pControl->SetVisible(false);
            }*/
        }
        return lRes;
    }
}